/**
 * \file SymbolTable.h
 *
 * Asteriskos Compiler 1
 * Written 2010-2011, by Anthony Berlin and Alexander Carlqvist
 *
 * This file is part of ICC.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef SYMBOL_TABLE_H
#define SYMBOL_TABLE_H

/// For some reason we need to declare the Symbol here to be able to use it, even though
/// it is declared and defined in "Symbol.h".
class Symbol;
class Parser;

#include "Symbol.h"

#include <GCB/Datatype.h>
#include <GCB/Object.h>

/// A SymbolTable is a table containing symbols, plain and simple.
class SymbolTable : public Object
{
private:
    /// The parent symbol table.
    SymbolTable* m_parent;

    /// A doubly-linked list containing all the local symbol tables of this symbol table.
    list<SymbolTable*>* m_stack;

public:
    /// Constructors for 'SymbolTable'.
    SymbolTable(SymbolTable* parent, Parser* parser);
    SymbolTable();

    /// Initialize the symbol table by setting default values to its data members and allocating
    /// memory or the declarations.
    void init();

    /// Push a symbol onto the stack of the symbol table.
    void push(Symbol* symbol);

    /// Returns the named symbol from this specific symbol table. Returns NULL if no symbol with
    /// the specified name was found.
    Symbol* get_symbol(string lexeme);

    /// Returns the named symbol from this symbol table or any symbol table global to this one.
    /// Returns NULL if no symbol with the specified name was found.
    Symbol* get_symbol_in_scope(string& lexeme);

    /// Returns the symbol table containing this one (its "parent").
    SymbolTable* get_parent() const;

    /// Returns the stack of local symbol tables.
    list<SymbolTable*>* get_stack() const;

    /// If an identifier has been declared, using datatypes as well, if we're talking functions,
    /// we return the symbol that this identifier+datatype combination represents. This function
    /// recursively searches all symbol tables that are global to this one, for a declaration.
    Symbol* is_declared(string lexeme, Symbol* comparisonSymbol = NULL, bool defunc = false);

    /// A hashtable containing all the declarations of this symbol table.
    unordered_map<string, Symbol*>* m_declarationTable;

    /// A doubly-linked list containing all the declarations of this symbol table.
    list<Symbol*>* m_declarationList;

    /// If this is a function body scope, this is the symbol associated with this scope.
    Symbol* m_funcSymbol;

    /// The parser to use when generating errors and warnings.
    Parser* m_parser;
};

#endif // SYMBOL_TABLE_H
